import json
import time

from django.core.files.storage import default_storage
from rest_framework.pagination import PageNumberPagination
from rest_framework.views import APIView
from django.db.models import Avg  # 推荐直接导入 Avg
from rest_framework.response import Response
from rest_framework import status
from rest_framework.viewsets import ViewSet, ModelViewSet

from mytools.my_mongodb import getconnection, getone, postone, deleteone
from .models import ProductCategory, Product, ProductReview,Banner,HistoryModel
from .serializers import (
    ProductCategorySerializer,
    ProductSerializer,
    ProductDetailSerializer, ProductReviewSerializer, BannerSerializer, HistorySerializer
)
from django.shortcuts import get_object_or_404
from django_filters import filterset
from django_filters.rest_framework import DjangoFilterBackend
from utils.myredis import r

# 创建过滤器
class ProductFilter(filterset.FilterSet):
    name = filterset.CharFilter(lookup_expr='icontains')  # 改为不区分大小写的包含
    category = filterset.NumberFilter()  # 明确添加分类过滤

    class Meta:
        model = Product
        fields = ["name", "category"]


class MyPage(PageNumberPagination):
    page_size = 9  # 与前端保持一致
    page_query_param = 'page'
    page_size_query_param = 'page_size'
    max_page_size = 100

    def get_paginated_response(self, data):
        return Response({
            'count': self.page.paginator.count,
            'results': data,
            'total_pages': self.page.paginator.num_pages,
            'current_page': self.page.number
        })
# 商品分类列表和详情
class CategoryListAPIView(APIView):
    def get(self, request):
        queryset = ProductCategory.objects.all()
        serializer = ProductCategorySerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class CategoryDetailAPIView(APIView):
    def get(self, request, pk):
        category = get_object_or_404(ProductCategory, pk=pk)
        serializer = ProductCategorySerializer(category)
        return Response(serializer.data, status=status.HTTP_200_OK)

# 商品列表和详情
class ProductListAPIView(APIView):
    pagination_class = MyPage
    filter_backends = [DjangoFilterBackend]
    filterset_class = ProductFilter

    def get(self, request):
        queryset = Product.objects.filter(is_active=True)

        # 应用过滤
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(request, queryset, self)

        # 应用分页
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)

        if page is not None:
            serializer = ProductSerializer(page, many=True)
            return paginator.get_paginated_response(serializer.data)

        serializer = ProductSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class HistoryListAPIView(APIView):
    def created(self,user_id,product_id,type_id):#用户id#商品id#分类id
        data=HistoryModel.objects.filter(user_id=user_id,product_id=product_id,type_id=type_id).first()
        if data:
            HistoryModel.objects.filter(user_id=user_id,product_id=product_id,type_id=type_id).update(number=data.number+1)
            return Response({'code':200,'message':'已存在'})
        else:
            HistoryModel.objects.create(user_id=user_id,product_id=product_id,type_id=type_id)
            return Response({'code':200,'message':'添加成功'})
class HistoryList(APIView):
    def get(self, request):
        user=request.query_params.get('userid')#用户id
        product=request.query_params.get('product')#商品id
        type=request.query_params.get('type')#分类id
        data=HistoryModel.objects.filter(user=user,product=product,type=type).first()
        serializer = HistorySerializer(data)
        return Response({'code':200,'data':serializer.data})

# 商品详情接口
class ProductDetailAPIView(APIView):
    def get(self, request, pk):
        product = get_object_or_404(Product, pk=pk)
        userid = request.query_params.get('userid')

        # 获取相关评论
        reviews = product.reviews.all().order_by('-created_at')[:5]

        # 获取同类别推荐产品
        related_products = Product.objects.filter(
            category=product.category,
            is_active=True
        ).exclude(id=product.id)[:4]

        # 序列化数据
        product_serializer = ProductDetailSerializer(product)
        reviews_serializer = ProductReviewSerializer(reviews, many=True)
        related_serializer = ProductSerializer(related_products, many=True)

        # 构建响应数据
        response_data = {
            'product': product_serializer.data,
            'reviews': reviews_serializer.data,
            'related_products': related_serializer.data,
            'review_count': product.reviews.count(),
            'average_rating': product.reviews.aggregate(Avg('rating'))['rating__avg'] or 0
        }
        if userid:
            HistoryListAPIView().created(userid, product.id, product.category.id)

        return Response(response_data, status=status.HTTP_200_OK)

# 商品评价列表和详情
# class ProductReviewListAPIView(APIView):
#     # 定义get方法，用于获取所有产品评论
#     def get(self, request):
#         # 获取所有产品评论
#         queryset = ProductReview.objects.all()
#         # 将产品评论序列化
#         serializer = ProductDetailSerializer(queryset, many=True)
#         # 返回序列化后的数据，状态码为200
#         return Response(serializer.data, status=status.HTTP_200_OK)


# class ProductReviewDetailAPIView(APIView):
#     def get(self, request, pk):
#         review = get_object_or_404(ProductReview, pk=pk)
#         serializer = ProductDetailSerializer(review)
#         return Response(serializer.data, status=status.HTTP_200_OK)

# 搜索
# 更新搜索视图
class SearchAPIView(APIView):
    pagination_class = MyPage
    filter_backends = [DjangoFilterBackend]
    # 定义过滤器
    filterset_class = ProductFilter

    def get(self, request):
        queryset = Product.objects.filter(is_active=True)

        # 应用过滤
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(request, queryset, self)

        # 应用分页
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)

        if page is not None:
            serializer = ProductSerializer(page, many=True)
            return paginator.get_paginated_response(serializer.data)

        serializer = ProductSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


# 文件上传存储到本地
class Upload(APIView):
    def post(self, request):
        file = request.data.get('file')
        uploadfile = default_storage.save(file.name, file)
        url = default_storage.url(uploadfile)
        return Response({'url': url})

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from mytools.qiniu_store import Qiniu_Tool
import os
import uuid

class QiniuUploadAPIView(APIView):
    """
    七牛云文件上传接口
    支持直接上传文件到七牛云存储
    """
    def post(self, request):
        # 获取上传的文件
        file_obj = request.data.get('file')
        print(file_obj)
        if not file_obj:
            return Response(
                {"code": 40001, "message": "No file uploaded"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 生成唯一的文件名
        ext = os.path.splitext(file_obj.name)[1]  # 获取文件扩展名
        file_name = f"{uuid.uuid4().hex}{ext}"  # 生成随机文件名

        # 临时保存文件到本地
        temp_file_path = f"/tmp/{file_name}"

        try:
            with open(temp_file_path, 'wb+') as destination:
                for chunk in file_obj.chunks():
                    destination.write(chunk)

            # 初始化七牛云工具
            qiniu_tool = Qiniu_Tool()

            # 上传文件到七牛云
            upload_result = qiniu_tool.qiniu_upload(temp_file_path, file_name)

            # 删除临时文件
            if os.path.exists(temp_file_path):
                os.remove(temp_file_path)

            # 检查上传结果
            if upload_result['code'] == 10000:
                return Response(
                    {
                        "code": 10000,
                        "message": "File uploaded successfully",
                        "data": {
                            "key": upload_result['data']['key'],
                            "url": upload_result['data']['url'],
                            "original_name": file_obj.name,
                            'file_name':file_name
                        }
                    },
                    status=status.HTTP_200_OK
                )
            else:
                return Response(
                    {
                        "code": upload_result['code'],
                        "message": upload_result.get('message', 'Upload failed'),
                        "details": upload_result.get('details', '')
                    },
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )

        except Exception as e:
            # 确保删除临时文件
            if os.path.exists(temp_file_path):
                os.remove(temp_file_path)

            return Response(
                {
                    "code": 50001,
                    "message": "File upload error",
                    "error": str(e)
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )




## 获取文件URL接口
class FileURLAPIView(APIView):
    """
    获取文件URL接口（精简版）
    """
    def get(self, request):
        """
        获取文件URL
        参数:
        - key: 文件key（必需）
        - fresh: 是否添加时间戳防止缓存（可选，true/false）
        """
        key = request.query_params.get('key')
        # 获取请求参数中的key值
        if not key:
            # 如果没有key值，返回错误信息
            return Response(
                {"code": 40001, "message": "Missing file key"},
                status=status.HTTP_400_BAD_REQUEST
            )

        fresh = request.query_params.get('fresh', 'false').lower() == 'true'

        # 获取请求参数中的fresh值，默认为false，如果为true则添加时间戳防止缓存
        qiniu_tool = Qiniu_Tool()
        file_url = qiniu_tool.get_file_url(key, fresh)

        # 调用Qiniu_Tool类中的get_file_url方法，获取文件URL
        return Response({
            "code": 10000,
            "data": {
                "url": file_url,
                "key": key
            }
        }, status=status.HTTP_200_OK)
from utils.myredis import r
import json
import time
class BannerListAPIView(APIView):
    def get(self, request):
        redis_data=r.get_code('banner_data')
        # r.r_delete('banner_data')
        if redis_data:
            # 如果获取到，则返回
            return Response({'code':200,'msg':'redis中获取到','data':json.loads(redis_data)})


        try:
             # 尝试获取锁
             lock_acquired=r.setnx_code('banner_data_lock',1)
             if not lock_acquired:
                         # 获取锁失败
                    # 等待0.1秒后重新获取
                    time.sleep(0.1)
                    # 从redis中获取banner数据
                    nlist = r.get_code('banner_data')
                    if nlist:
                        # 如果获取到，则返回
                        return Response({"code": 200, "msg": "从缓存获取成功(重新)", "data": json.loads(nlist)})
                    # 如果获取不到，则返回系统繁忙
                    return Response({"code": 503, "msg": "系统繁忙，请稍后再试"}, status=503)
             # 获取锁成功
             else:

                # 从mysql中获取banner数据
                banners = Banner.objects.all().order_by('order', '-created_at')
                # 序列化
                serializer = BannerSerializer(banners, many=True)
                # 将数据存入redis中，设置过期时间为1天
                r.set_code('banner_data',60*60*24,json.dumps(serializer.data))
                # 返回数据
                return Response({'code':200,'msg':'mysql中获取到','data':serializer.data})
        finally:
            # 释放锁
            r.r_delete('banner_data_lock')



class Mongo(APIView):
    def get(self, request):
        sid = request.query_params.get("sid")
        if sid:
            try:
                data=getone(sid)
                return Response({'code':200,'msg':'ok','data':data})
            except Exception as e:
                return Response({'code':500,'error':e})
        else:
            try:
                data=getconnection()
                return Response({'code':200,'msg':'ok','data':data})
            except Exception as e:
                return Response({'code':500,'error':e})

    def post(self, request):
        try:
            document =request.data
            postone(document)
            return Response({'code':200,'msg':'ok'})
        except Exception as e:
            return Response({'code':500,'error':e})
    def delete(self, request):
        try:
            name =request.data.get("name")
            deleteone(name)
            return Response({'code':200,'msg':'ok'})
        except Exception as e:
            return Response({'code':500,'error':e})




